package com.wbp.cms.qatest;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.wbp.cms.qatest.service.AService;
import com.wbp.cms.qatest.service.AServiceImpl;
import com.wbp.cms.qatest.service.BService;
import com.wbp.cms.qatest.service.CServiceImpl;
import com.wbp.cms.qatest.service.MyAdvice;
import com.wbp.cms.qatest.service.MyAfterAdvice;

public class SrpingTransactionTest {

	@SuppressWarnings("resource")
	ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
	
	TransactionTemplate  tt = ctx.getBean(TransactionTemplate.class);
	
	
	public AService getAService(){
		System.out.println("AService class"+getClass());
		AService service = ctx.getBean(AService.class) ;
		System.out.println("service:"+service);
		return service ;
	}
	
	public BService getBService(){
		System.out.println("BService class"+getClass());
		BService service = ctx.getBean(BService.class) ;
		System.out.println("service:"+service);
		return service ;
	}
	
	public void testBean(){
		AService service = ctx.getBean("aService",AService.class) ;
		Class<?> aCls = AopProxyUtils.ultimateTargetClass(service) ;
		
		System.out.println("service: " + service +",aCls: "+ aCls );
        boolean isSingleton = ctx.isSingleton("aService") ;
        System.out.println(isSingleton + " - "+ctx.isPrototype("aService"));
        String[] array = ctx.getAliases("aService") ;
        System.out.println(array);
        for(String a: array)
        	 System.out.println(a);
        int count = ctx.getBeanDefinitionCount() ;
        System.out.println("count:"+count);
        Map<String,Object> map = ctx.getBeansWithAnnotation(org.springframework.stereotype.Service.class);
        System.out.println(map);
	}
	
	public void testBean2(){
		AService aService = ctx.getBean("aServiceProxy",AService.class) ;
		AService as =ctx.getBean("aService",AService.class) ;
		aService.test1();
		System.out.println(aService);
		System.out.println("-------------------");
		as.test1();
	}
	
	public void testBean3(){
		AService as = new AServiceImpl();
		System.out.println( as.getClass().isInterface() ) ;
		ProxyFactory pf = new ProxyFactory(as);
		
		RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();
		MyAdvice   myAdvice= new MyAdvice();
		advisor.setAdvice(myAdvice);
		advisor.setPattern(".*test*.*");  // 1. 如果target是有接口,此属性无效
		// pf.addAdvice(myAdvice);  // 把advice  设置到advisor中
		pf.addAdvisor(advisor);
		AService asproxy = (AService)pf.getProxy();
		asproxy.test2() ;
		System.out.println(asproxy);
	}
	
	public void testBean4(){
		CServiceImpl as = new CServiceImpl();
		System.out.println( as.getClass().isInterface() ) ;
		ProxyFactory pf = new ProxyFactory(as);
		
		RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();
		MyAdvice   myAdvice= new MyAdvice();
		MyAfterAdvice  afterAdvice = new MyAfterAdvice();
		advisor.setAdvice(myAdvice);
		//advisor
		advisor.setPattern(".*test*.*");  // 1. 如果target是有接口,此属性无效
		pf.addAdvice(myAdvice);
		pf.addAdvisor(advisor);
		CServiceImpl asproxy = (CServiceImpl)pf.getProxy();
		asproxy.test2() ;
		System.out.println(asproxy);
		Class<? extends CServiceImpl> cls = as.getClass() ;
		Method[] ms = cls.getDeclaredMethods() ;
		for(Method m : ms){
			System.out.println( AopUtils.isEqualsMethod(m) );
			System.out.println(AopUtils.isHashCodeMethod(m));
			System.out.println(AopUtils.isToStringMethod(m));
		}
		
	}
	
	public static void main(String[] args) {

		SrpingTransactionTest stt = new SrpingTransactionTest();
		// stt.test1(); 
		// stt.getBService().test1();
		stt.testBean3();
		
		List<String> list = new ArrayList<String>();
		list.add(null) ;
		list.add(null) ;
		for(String s:list)
			System.out.println(s);
	}

	
	public void test1(){
		 tt.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); 
		tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		//tt.setTimeout(300);
		tt.execute(new TransactionCallback<String>() {

			 
			@Override
			public String doInTransaction(TransactionStatus status) {
				 
				 Thread t =Thread.currentThread() ;
				 System.out.println("test1 currentThread:"+t);
				System.out.println("test1 :"+t.getClass());
				Field field = null ;
				try {
					field = t.getClass().getDeclaredField("threadLocals");
					field.setAccessible(true); 
					Object obj = field.get(t) ;
					System.out.println("test1 obj:"+obj );
					Class clas = Class.forName("java.lang.ThreadLocal$ThreadLocalMap") ;
					Field field2 =clas.getDeclaredField("table") ;
					field2.setAccessible(true);
					Object[] obj2 = (Object[])field2.get(obj) ;
					for(Object oj:obj2){
						if(oj!=null ){
							Class cls = Class.forName("java.lang.ThreadLocal$ThreadLocalMap") ;
						}
					}
						 

				} catch (NoSuchFieldException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (SecurityException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				
				 try {
					 System.out.println("--------");
					 Thread.sleep(100);
					 boolean f = test2();
					 if(!f)
						 status.setRollbackOnly();
				} catch (Exception e) {
					e.printStackTrace();
					 
				}finally{
					 
					//status.setRollbackOnly();
				}
				return "";
			}
		}) ;
	}
	
	public boolean test2(){
		tt.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); 
		tt.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		//tt.setTimeout(300);
		final String r = tt.execute(new TransactionCallback<String>() {

			@Override
			public String doInTransaction(TransactionStatus status) {
				Thread t =Thread.currentThread() ;
				 System.out.println("test2 currentThread:"+t);
				 System.out.println("test2 : "+t.getClass());
				 try {
					 System.out.println("--------");
					 Thread.sleep(100);
					 status.setRollbackOnly();
				} catch (Exception e) {
					e.printStackTrace();
					 
				}finally{
					 
					
				}
				return "false";
			}
		}) ;
		return r.equals("false")?false :true;
	}
	
}
